package com.sxj.shop.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("*.file")
public class FileServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path = request.getServletPath();
        switch (path) {
            case "/upload.file":
                upload(request, response);
                break;
            case "/download.file":
                download(request, response);
                break;
            case "/download2.file":
                download2(request, response);
                break;
        }
    }

    protected void upload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 针对普通表单数据的
//        String username = request.getParameter("username");
//        String file = request.getParameter("file");
//        System.out.println("username:"+username+",file:"+file);

        // 如果是二进制流数据,必须通过二进制流的方式获取
//        InputStream in = request.getInputStream();
//        byte[] b = new byte[1024];
//        int i = in.read(b);
//        System.out.println(new String(b, 0, i));

        // 通过apache提供的第三方依赖对二进制流数据做解析操作
        // 注意:该依赖实现的不是文件上传,仅仅只是文件数据解析
        // 1.获取解析工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 2.根据解析工厂获取对应的解析器
        ServletFileUpload upload = new ServletFileUpload(factory);
        try {
            // 3.开始解析
            List<FileItem> items = upload.parseRequest(request);
            Map<String, FileItem> map = new HashMap<>();
            for (FileItem item : items) {
//                System.out.println("表单数据的key:"+item.getFieldName());
//                System.out.println("文件名:"+item.getName());
//                System.out.println("具体内容:"+item.getString());
//                switch (item.getFieldName()){
//                    case "username":
//                        System.out.println("用户名为:"+item.getString());
//                        break;
//                    case "file":
//                        System.out.println("文件名为:"+item.getName());
//                        System.out.println("文件内容:"+item.getString());
//                }
                map.put(item.getFieldName(), item);
            }
//            System.out.println("用户名:"+map.get("username").getString());
//            System.out.println("文件名:"+map.get("file").getName());
//            System.out.println("文件内容:"+map.get("file").getString("utf-8"));

            // 如果是jsp文件与Java文件,则不允许上传
            FileItem file = map.get("file");
            String fileName = file.getName();
            if (fileName.endsWith(".jsp")) {
                request.setAttribute("uploadMsg", "上传失败,不允许上传JSP文件");
                request.getRequestDispatcher("/jsp/upload.jsp").forward(request, response);
                return;
            }
            if (fileName.endsWith(".java")) {
                request.setAttribute("uploadMsg", "上传失败,不允许上传Java文件");
                request.getRequestDispatcher("/jsp/upload.jsp").forward(request, response);
                return;
            }

            // 将文件上传到服务器根目录的upload目录中,每天一个子目录,子目录格式:yyyyMMdd
            String path = getServletContext().getRealPath("/upload/" + new SimpleDateFormat("yyyyMMdd").format(new Date()));
            File f = new File(path);
            f.mkdirs();

            // 将文件上传到服务器
            // 参数为:上传之后的文件
            file.write(new File(path, file.getName()));
        } catch (FileUploadException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected void download(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取服务器上资源位置
        String path = getServletContext().getRealPath("/js/jquery-3.4.1.min.js");
        FileInputStream in = null;
        OutputStream out = null;

        try {
//            in = new FileInputStream(path);
//            out = response.getOutputStream();
//
//            byte[] b = new byte[1024];
//            int i;
//            while ((i = in.read(b)) != -1) {
//                out.write(b, 0, i);
//            }

            // 此时的文件默认还是通过在线打开的方式或者右键另存为的方式实现下载
            // 该方式不太友好,我们希望点击之后直接下载
            // 此时可以通过响应头信息中的Content-disposition属性来实现
            // 其值遵循MIME协议,存在两种值
            // 1.attachment:以附件的方式进行下载
            // 2.inline:默认值,以在线打开的方式进行下载
            // response.setHeader("Content-disposition","attachment");
            // 此时可以通过附件下载了,但是下载的文件名并不是真实的文件名,而是以当前请求名作为文件名显示的
            // 因此,我们可以手动设置文件名,也是通过Content-disposition设置的
            // 其值可以分为两块区域,以分号分隔,左边表示附件方式,右边指定文件名
            // response.setHeader("Content-disposition","attachment;filename=jquery-3.4.1.min.js");
            // 如果文件名是一个中文,需要使用ISO-8859-1的字符集
            response.setHeader("Content-disposition",new String("attachment;filename=中文.js".getBytes(),"ISO-8859-1"));
            in = new FileInputStream(path);
            out = response.getOutputStream();

            byte[] b = new byte[1024];
            int i;
            while ((i = in.read(b)) != -1) {
                out.write(b, 0, i);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    protected void download2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path = getServletContext().getRealPath("/lib/jstl-1.2.jar");

        FileInputStream in = null;
        OutputStream out = null;

        try {
            response.setHeader("Content-disposition","attachment;filename=jstl-1.2.jar");
            in = new FileInputStream(path);
            out = response.getOutputStream();

            byte[] b = new byte[1024];
            int i;
            while ((i = in.read(b)) != -1) {
                out.write(b, 0, i);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
